#ifndef _UDS_CLIENT_H
#define _UDS_CLIENT_H
#include <string>
#include <map>
#include <vector>
#include <sys/poll.h>
#include <sys/epoll.h>
#include "udsCommon.h"
#include "template/template_thread.hpp"

typedef struct _FuncHandler
{
    udsFunc func;
    stdUdsFunc stdfunc;
    stdUdsFunc *pStdFunc;
    void *pObj;
}FuncHandler, *p_FuncHandler;

typedef std::map<int, p_FuncHandler> udsClientFuncMap;



class udsClient
{
public:
    static bool shortRequest(const char *path, int cmd, void *msg, int msgLen, udsFunc func ,void *obj = NULL);
    static bool shortRequest(const char *ip, int port, int cmd, void *msg, int msgLen, udsFunc func,void *obj = NULL);
    static bool shortRequestByFd(int fd, int cmd, void *msg, int msgLen, udsFunc func, void *obj);

public:
    bool startClient();
    bool startClient(const char *thread_name);
    int connectedTcp(const char *ip, int port, udsFunc func, void *pObj);
	int connectedUds(const char *paths, udsFunc func, void *pObj);

    int connectedTcp_v1(const char *ip, int port, stdUdsFunc func, void *pObj);
    int connectedTcp_v2(const char *ip, int port, stdUdsFunc *func, void *pObj);
	int connectedUds_v1(const char *paths, stdUdsFunc func, void *pObj);
    int connectedUds_v2(const char *paths, stdUdsFunc *func, void *pObj);


    

    void stopClient();
    void disConnectFd(int fd);
    void disConnectAll();


    int sendMsg(int fd, int cmd, void *msg, int msgLen);
    int sendPacks(int fd, int cmd, void **frame_addr, size_t *frame_size, int pack_count);
    //################# 内部线程逻辑使用 start ##############
    void udsPollDisponse();
    //################# 内部线程逻辑使用 end ##############
private:
    //将fd 移除 poll 监听容器
    void _removePollFd(int fd);
    //将fd 加入 poll 监听容器
    void _pushPollFd(int fd);

private:
    bool udsClientInit_;
    std::vector<pollfd> pollFdVector_;  // poll 监听的fd 容器
    std::mutex pollFdVectorMutex_; //pollFdVector_ 编辑锁
    template_thread<udsClient> udsClientThread_; //poll_dispose 线程句柄
    udsClientFuncMap udsFuncMap_; // 注册的事件回调存放容器
};

class uds_client_base {
public:
	uds_client_base(const char * uds_path);

	virtual ~uds_client_base();

	/**
	 * @brief:	创建一个长连接用于发送消息, 消息的回调在注册的函数中
	 *
	 * @param func 注册的函数
	 * @param pObj 用户数据
	 * @param cmd 命令码
	 * @param msg 携带的消息
	 * @param msg_len 消息长度
	 *
	 * @return fd 该长连接的文件描述符
	 */
	int create_long_connect(stdUdsFunc  *func, void *pObj, int cmd, void * msg, int msg_len);

	int create_long_connect(stdUdsFunc  func, void *pObj, int cmd, void * msg, int msg_len);

	
	/**
	 * @brief:	销毁一个长连接
	 *
	 * @param fd 长连接的 句柄
	 */
	void destroy_long_connect(int fd);

	/**
	 * @brief: 创建一个短链接用于发送消息 无需回调接收	
	 *
	 * @param cmd 命令码
	 * @param msg 携带的消息
	 * @param msg_len 消息长度
	 *
	 * @return 是否成功
	 */
	int create_short_connect(int cmd, void * msg, int msg_len);

	/**
	 * @brief:	给一个长链接发送消息
	 *
	 * @param fd
	 * @param cmd
	 * @param msg
	 * @param msgLen
	 *
	 * @return 
	 */
    int send_msg_with_fd(int fd, int cmd, void *msg, int msgLen);
private:
	udsClient * _instance = NULL;
	char * _uds_path = NULL;
	bool _init = false;
};

#endif //_UDS_CLIENT_H




